package com.qiyuexinxi.chat.service.impl;

import com.qiyuexinxi.chat.domain.Recommend;
import com.qiyuexinxi.chat.domain.User;
import com.qiyuexinxi.chat.dto.request.CompleteInfoRequest;
import com.qiyuexinxi.chat.dto.request.LoginRequest;
import com.qiyuexinxi.chat.dto.request.RegisterRequest;
import com.qiyuexinxi.chat.exception.reg.exception.BizErrorCodeEnum;
import com.qiyuexinxi.chat.exception.reg.exception.BizException;
import com.qiyuexinxi.chat.mapper.RecommendMapper;
import com.qiyuexinxi.chat.mapper.UserMapper;
import com.qiyuexinxi.chat.service.LoginService;
import com.qiyuexinxi.chat.util.DateUtil;
import com.qiyuexinxi.chat.util.EncryptUtil;
import com.qiyuexinxi.chat.util.RandomNumUtil;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.text.ParseException;
import java.util.concurrent.TimeUnit;

/**
 * @author yangxingyu
 * @date 2020/2/27
 * @description
 */
@Service
public class LoginServiceImpl implements LoginService {

    //手机验证码有效时间5分钟
    private final Long CODE_EXPIRE_TIME = 5 * 60L;
    private final String PHONE_CODE_PREFIX = "phonecode:";
    //限制每个手机号每分钟只能发送一次
    private final Long CODE_SEND_EXPIRE_TIME = 60L;
    private final String PHONE_CODE_SEND = "phonecode:send:";

    private final String SALT = "good_chat";

    @Autowired
    StringRedisTemplate stringRedisTemplate;
    @Autowired
    SendMessageServiceImpl sendMessageService;
    @Autowired
    UserMapper userMapper;
    @Autowired
    RecommendMapper recommendMapper;

    @Override
    public Integer register(RegisterRequest registerReques) {
        //校验该手机号是否已经注册过
        User user1 = userMapper.selectByPhone(registerReques.getPhone());
        if (user1 != null) {
            throw new BizException(BizErrorCodeEnum.REGISTERED);
        }
        String key = PHONE_CODE_PREFIX + registerReques.getPhone();
        String phoneCode = stringRedisTemplate.opsForValue().get(key);
        //redis中验证码不能为空
        if (StringUtils.isBlank(phoneCode)) {
            throw new BizException(BizErrorCodeEnum.GET_PHONE_CODE_REDIS_FAILED);
        }
        //比较用户输入验证码和redis中验证码
        if (!registerReques.getPhoneCode().equals(phoneCode)) {
            throw new BizException(BizErrorCodeEnum.PHONE_CODE_ERROR);
        }
        String chatCode = "";
        String substring = "0";
        int chatCodeCount = 1;
        while ("0".equals(substring) || chatCodeCount != 0) {
            chatCode = RandomNumUtil.getRandomNum(6);
            substring = chatCode.substring(0, 1);
            chatCodeCount = userMapper.selectChatCodeCount(chatCode);
        }
        User user = new User();
        BeanUtils.copyProperties(registerReques, user);
        user.setChatCode(chatCode);
        user.setUsername("聊聊号" + chatCode);
        user.setPassword(EncryptUtil.encryptPWD(registerReques.getPassword(), SALT));
        int i = userMapper.insertSelective(user);
        if (i <= 0) {
            throw new BizException(BizErrorCodeEnum.REGISTER_USER_FAILED);
        }
        return user.getUserId();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean completeInfo(CompleteInfoRequest completeInfoRequest){
        //判断用户是否存在
        User user = userMapper.selectByPrimaryKey(completeInfoRequest.getUserId());
        if (user == null || user.getDeleted() == 0) {
            throw new BizException(BizErrorCodeEnum.USER_NOT_EXIST);
        }
        BeanUtils.copyProperties(completeInfoRequest, user);
        user.setAge(DateUtil.getAgeByBirth(DateUtil.convertStringToDate(completeInfoRequest.getBirthday())) + "");
        int userCount = userMapper.updateByPrimaryKeySelective(user);
        int recommendCount = 1;
        if (StringUtils.isNotEmpty(completeInfoRequest.getReferrerChatCode())) {
            User referrerUser = userMapper.selectUserByChatCodeCount(completeInfoRequest.getReferrerChatCode());
            if(referrerUser==null){
                throw new BizException(BizErrorCodeEnum.REFERRERCHAT_USER_NOT_EXIST);
            }
            Recommend recommend = new Recommend();
            recommend.setReferrer(referrerUser.getUserId());
            recommend.setUserId(completeInfoRequest.getUserId());
            recommendCount = recommendMapper.insertSelective(recommend);
        }
        if (userCount == 0 || recommendCount == 0) {
            throw new BizException(BizErrorCodeEnum.COMPLETE_INFORMATION_FAILED);
        }
        return true;
    }

    @Override
    public Integer login(LoginRequest loginReques) {
        //校验该手机号是否注册过
        User user = userMapper.selectByPhone(loginReques.getPhone());
        if (user == null) {
            throw new BizException(BizErrorCodeEnum.UNREGISTERED);
        }
        String password = EncryptUtil.encryptPWD(loginReques.getPassword(), SALT);
        if (!user.getPassword().equals(password)) {
            throw new BizException(BizErrorCodeEnum.PASSWORD_ERROR);
        }
        return user.getUserId();
    }

    @Override
    public String getPhoneCode(String phone) {
        //校验该手机号是否已经注册过
//        User user1 = userMapper.selectByPhone(phone);
//        if (user1 != null) {
//            throw new BizException(BizErrorCodeEnum.REGISTERED);
//        }
        String key = PHONE_CODE_PREFIX + phone;
        String sendKey = PHONE_CODE_SEND + phone;
        //2.验证手机号60秒内是否已经发送过验证码
        String s = stringRedisTemplate.opsForValue().get(sendKey);
        if (!StringUtils.isBlank(stringRedisTemplate.opsForValue().get(sendKey))) {
            throw new BizException(BizErrorCodeEnum.SENDING_CODE);
        }
        //3.随机生成4位验证码
        String verificationCode = RandomNumUtil.getRandomNum(4);
        //4.发送短信给手机号
        sendMessageService.sendMessage(phone, verificationCode);
        //5将手机号验证码存入缓存并设置有效期 TimeUnit.SECONDS 单位：秒
        stringRedisTemplate.opsForValue().set(key, verificationCode, CODE_EXPIRE_TIME, TimeUnit.SECONDS);
        stringRedisTemplate.opsForValue().set(sendKey, verificationCode, CODE_SEND_EXPIRE_TIME, TimeUnit.SECONDS);
        if (StringUtils.isBlank(stringRedisTemplate.opsForValue().get(key))) {
            throw new BizException(BizErrorCodeEnum.PHONE_CODE_REDIS_FAILED);
        }
        return "验证码发送成功";
    }

    @Override
    public Integer rePassword(RegisterRequest registerReques) {
        //校验该手机号是否已经注册过
        User user = userMapper.selectByPhone(registerReques.getPhone());
        if (user == null) {
            throw new BizException(BizErrorCodeEnum.UNREGISTERED);
        }
        String key = PHONE_CODE_PREFIX + registerReques.getPhone();
        String phoneCode = stringRedisTemplate.opsForValue().get(key);
        //redis中验证码不能为空
        if (StringUtils.isBlank(phoneCode)) {
            throw new BizException(BizErrorCodeEnum.GET_PHONE_CODE_REDIS_FAILED);
        }
        //比较用户输入验证码和redis中验证码
        if (!registerReques.getPhoneCode().equals(phoneCode)) {
            throw new BizException(BizErrorCodeEnum.PHONE_CODE_ERROR);
        }
        int i = userMapper.updateByPhone(registerReques.getPhone(), EncryptUtil.encryptPWD(registerReques.getPassword(), SALT));
        if (i <= 0) {
            throw new BizException(BizErrorCodeEnum.REGISTER_USER_FAILED);
        }
        return user.getUserId();
    }
}
